namespace SimpleWebServices.Web.Mvc
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
    using SimpleWebServices.Configuration;
    using SimpleWebServices.Security.Cryptography;
    using SimpleWebServices.Web.Routing;

    [InternalServerError]
    [Allow(Methods = "GET, HEAD, OPTIONS")]
    [ContentMD5]
    public sealed class FileController : Controller, IRegisterRoutes
    {
        public void Register(RouteCollection routes)
        {
            if (null == routes)
            {
                throw new ArgumentNullException("routes");
            }

            routes.Add(new FileRoute());
        }

        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "ASP.NET MVC requires the method to be an instance member.")]
        public ActionResult Representation()
        {
            ActionResult result = null;

            FileSetting setting = FileConfiguration.Setting(HttpContextFactory.Current.Request.Path);
            if (null != setting)
            {
                FileInfo file = setting.File;
                if (null != file && file.Exists)
                {
                    result = new FileStreamResult(file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite), setting.ContentType);
                }

                if (null != result)
                {
                    HttpResponseBase response = HttpContextFactory.Current.Response;
                    if (HttpCacheability.NoCache == setting.Cacheability)
                    {
                        response.Cache.SetCacheability(HttpCacheability.NoCache);
                    }
                    else if ("expires".Equals(setting.CacheCondition, StringComparison.OrdinalIgnoreCase))
                    {
                        response.Cache.SetCacheability(setting.Cacheability);
                        response.Cache.SetExpires(DateTimeFactory.UtcNow.Add(setting.Duration));
                        response.Cache.SetMaxAge(setting.Duration);
                    }
                    else if ("etag".Equals(setting.CacheCondition, StringComparison.OrdinalIgnoreCase))
                    {
                        response.Cache.SetCacheability(setting.Cacheability);
                        response.Cache.SetETag(MD5Hash.Compute(file));
                    }
                    else if ("last-modified".Equals(setting.CacheCondition, StringComparison.OrdinalIgnoreCase))
                    {
                        response.Cache.SetCacheability(setting.Cacheability);
                        response.Cache.SetLastModified(file.LastWriteTimeUtc);
                    }
                }
            }

            return result ?? new NotFoundResult();
        }
    }
}